package pay

import (
	"context"
	"database/sql"
	"errors"
	"fmt"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gtime"
	"github.com/gogf/gf/v2/util/gconv"
	"github.com/plutov/paypal/v4"
	"log"
	"strconv"
	"video-api/internal/consts"
	"video-api/internal/dao"
	"video-api/internal/model/entity"
	"video-api/internal/model/input"
	"video-api/internal/model/out"
	"video-api/internal/service"
)

var payPalClient *paypal.Client

func PayPalClient(clientId, secretID string) {
	c, err := paypal.NewClient(clientId, secretID, paypal.APIBaseSandBox)
	if err != nil {
		return
	}
	payPalClient = c
}

type paypalPayment struct{}

func init() {
	service.RegisterPaymentPayService(&paypalPayment{})
}

func (s *paypalPayment) CreateOrder(ctx context.Context, orderInfo *out.OrderEntity) (*paypal.Order, error) {
	// 获取访问令牌
	_, err := payPalClient.GetAccessToken(context.TODO())
	if err != nil {
		log.Fatalf("Failed to get access token: %v", err)
	}

	// 创建支付订单
	purchaseUnits := make([]paypal.PurchaseUnitRequest, 1)
	amount := fmt.Sprintf("%.2f", orderInfo.Amount) // 支付金额
	purchaseUnits[0] = paypal.PurchaseUnitRequest{
		Amount: &paypal.PurchaseUnitAmount{
			Currency: orderInfo.Currency,
			Value:    amount,
		},
		Description: "充值订单",
	}

	//payer := &paypal.CreateOrderPayer{}
	order, err := payPalClient.CreateOrder(context.TODO(), paypal.OrderIntentCapture, purchaseUnits, nil, nil)
	if err != nil {
		log.Fatalf("Failed to create order: %v", err)
	}
	return order, nil
}

// 回调(可以利用上面的回调链接实现)
func (s *paypalPayment) OrderPay(ctx context.Context, in *input.OrderPay) (orderInfo *out.OrderEntity, err error) {
	// 获取订单信息
	oModel := dao.Orders.Ctx(ctx)
	orders := new(entity.Orders)
	err = oModel.Where("id = ?", in.OrderId).Scan(orders)
	if err != nil {
		return nil, err
	}
	// 获取paypal客户端连接
	_, err = payPalClient.GetAccessToken(ctx)
	if err != nil {
		return nil, err
	}
	ctor := paypal.CaptureOrderRequest{}
	var failReason string
	order, err := payPalClient.CaptureOrder(ctx, orders.PlatformOrderId, ctor)
	if err != nil {
		failReason = err.Error()
		return nil, err
	}

	orderInfo = new(out.OrderEntity)
	err = gconv.Structs(orders, orderInfo)
	if err != nil {
		return nil, err
	}
	updateOrder := g.Map{
		"payment_time": gtime.Now(),
	}
	//查看回调完成后订单状态是否支付完成。
	if (*order).Status == "COMPLETED" {
		// 修改订单（支付成功）
		updateOrder["status"] = consts.PAY_COMPLETED
		// 商家到手利润
		if len(order.PurchaseUnits) > 0 && order.PurchaseUnits[0].Payments != nil &&
			len(order.PurchaseUnits[0].Payments.Captures) > 0 && order.PurchaseUnits[0].Payments.Captures[0].SellerReceivableBreakdown != nil &&
			order.PurchaseUnits[0].Payments.Captures[0].SellerReceivableBreakdown.NetAmount != nil {
			profit := 0.0
			profit, err = strconv.ParseFloat(order.PurchaseUnits[0].Payments.Captures[0].SellerReceivableBreakdown.NetAmount.Value, 64)
			if err != nil {
				return nil, err
			}
			updateOrder["profit"] = profit
		}
		_, err = oModel.Data(updateOrder).Where("id", orderInfo.Id).Update()
		if err != nil {
			return nil, err
		}
		// 增加用户账号余额
		user := new(entity.Users)
		err = dao.Users.Ctx(ctx).Where("id = ?", orderInfo.UserId).Scan(user)
		if err != nil && !errors.Is(err, sql.ErrNoRows) {
			return nil, err
		}
		if user.Id == 0 {
			return nil, errors.New("用户不存在")
		}
		// 获取商品信息
		goodsInfo := new(entity.Goods)
		err = dao.Goods.Ctx(ctx).Where("id = ?", orderInfo.GoodsId).Scan(goodsInfo)
		if err != nil && !errors.Is(err, sql.ErrNoRows) {
			return nil, err
		}
		if goodsInfo.Id == 0 {
			return nil, errors.New("商品不存在")
		}
		user.Coins += int(goodsInfo.Coins)
		user.Bonus += int(goodsInfo.Bonus)
		_, err = dao.Users.Ctx(ctx).Where("id = ?", user.Id).Data(user).Update()
		if err != nil {
			return nil, err
		}
	} else {
		// 修改订单
		updateOrder["status"] = consts.PAY_FAIL
		updateOrder["fail_reason"] = failReason
		_, err = oModel.Data(updateOrder).Where("id", orderInfo.Id).Update()
		if err != nil {
			return nil, err
		}
	}
	return orderInfo, nil
}
